package wanxiang

import (
	"encoding/json"
	"fmt"
	"gitee.com/gam6it/SecToolkit/utils/hash"
	"gitee.com/gam6it/SecToolkit/utils/http2"
	"sort"
	"strings"
	"time"
)

/**
青藤万相Client主文件
*/

type Client struct {
	URI      string        `json:"-"`
	UserName string        `json:"username,omitempty"`
	Password string        `json:"password,omitempty"`
	Sign     Sign          `json:"-"`
	TimeOut  time.Duration `json:"-"`
}

type Sign struct {
	CompanyID string `json:"comId,omitempty"`
	JWT       string `json:"jwt,omitempty"`
	SignKey   string `json:"signKey,omitempty"`
}

func NewClient(uri, username, password string, timeout time.Duration) (*Client, error) {
	var client = Client{
		URI:      uri,
		UserName: username,
		Password: password,
		TimeOut:  timeout,
	}
	err := client.login()
	return &client, err
}

func (c *Client) login() error {
	var err error
	type resp struct {
		Success   bool   `json:"success"`
		ErrorCode string `json:"errorCode"`
		ErrorDesc string `json:"errorDesc"`
		Data      Sign   `json:"data"`
	}
	var result resp
	var opts = []func(req *http2.Req){
		http2.ContentType(http2.ContentTypeJson),
		http2.JsonParam(c),
		http2.TimeOut(c.TimeOut),
	}
	api := c.URI + "v1/api/auth"
	err = http2.RequestJsonUnmarshal(http2.MethodPost, api, &result, opts...)
	if err == nil && result.ErrorCode == "" && result.ErrorDesc == "" {
		// log.Println("登录成功！")
		b, err := json.Marshal(result.Data)
		if err != nil {
			return err
		}
		return json.Unmarshal(b, &c.Sign)
	}
	return fmt.Errorf("登录失败，错误原因:%v,返回中ErrorCode:%s,返回中ErrorDesc:%s", err, result.ErrorCode, result.ErrorDesc)
}

func (c *Client) Request(method, api string, result any, req any) error {
	var err error
	var toSign string
	if c.Sign.JWT == "" || c.Sign.CompanyID == "" || c.Sign.SignKey == "" { // 未登录
		if err = c.login(); err != nil {
			return err
		}
	}
	// 当前时间戳
	nowTimeUnix := time.Now().Unix()
	ts := fmt.Sprintf("%d", nowTimeUnix)
	// log.Println("请求参数：", req)
	if req != nil {
		var info, paramStr string
		if method == http2.MethodGet { // 如果是GET请求
			var params map[string]interface{}
			// 通过序列化获取param
			b, err := json.Marshal(req)
			if err != nil {
				return err
			}
			// fmt.Println(string(b))
			err = json.Unmarshal(b, &params)
			if err != nil {
				return err
			}
			var keys []string
			for key := range params {
				keys = append(keys, key)
			}
			sort.Sort(sort.StringSlice(keys))
			for _, key := range keys {
				value := fmt.Sprintf("%v", params[key])
				info += key + value
				paramStr += key + "=" + value + "&"
			}
			paramStr = strings.TrimSuffix(paramStr, "&")
			toSign = hash.Sha1(c.Sign.CompanyID + info + ts + c.Sign.SignKey)
			err = http2.RequestJsonUnmarshal(method, c.URI+api+"?"+paramStr, &result,
				http2.ContentType(http2.ContentTypeJson),
				http2.AddHeader("comId", c.Sign.CompanyID),
				http2.AddHeader("timestamp", ts),
				http2.AddHeader("sign", toSign),
				http2.AddHeader("Authorization", "Bearer "+c.Sign.JWT))
			// log.Println("==========", result, err)
			return err
		} else if method == http2.MethodPost || method == http2.MethodPut || method == http2.MethodDelete {
			b, err := json.Marshal(req)
			if err != nil {
				return err
			}
			// fmt.Println("参数：", string(b))
			toSign = hash.Sha1(c.Sign.CompanyID + string(b) + ts + c.Sign.SignKey)
			err = http2.RequestJsonUnmarshal(method, c.URI+api, &result,
				http2.ContentType(http2.ContentTypeJson),
				http2.AddHeader("comId", c.Sign.CompanyID),
				http2.AddHeader("timestamp", ts),
				http2.AddHeader("sign", toSign),
				http2.AddHeader("Authorization", "Bearer "+c.Sign.JWT))
			// log.Println("==========", result, err)
			return err
		}
	} else {
		toSign = hash.Sha1(c.Sign.CompanyID + ts + c.Sign.SignKey)
		err = http2.RequestJsonUnmarshal(method, c.URI+api, &result,
			http2.ContentType(http2.ContentTypeJson),
			http2.AddHeader("comId", c.Sign.CompanyID),
			http2.AddHeader("timestamp", ts),
			http2.AddHeader("sign", toSign),
			http2.AddHeader("Authorization", "Bearer "+c.Sign.JWT))
		// log.Println("==========", result, err)
		return err
	}
	return nil
}
